package com.cencat.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.utils.PaginationHelper;
import com.cencat.common.response.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.util.StringUtils;
import com.cencat.user.config.CacheConfig;
import com.cencat.user.dto.PermissionCreateDTO;
import com.cencat.user.dto.PermissionQueryDTO;
import com.cencat.user.dto.PermissionUpdateDTO;
import com.cencat.user.entity.Permission;
import com.cencat.user.mapper.PermissionMapper;
import com.cencat.user.service.PermissionService;
import com.cencat.user.vo.PermissionListVO;
import com.cencat.user.vo.PermissionVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.cencat.common.utils.CencatStringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限服务实现类
 * @author cencat
 * @since 2024-01-01
 */
@Service
@Slf4j
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "permissionPage", allEntries = true)
    public Long createPermission(PermissionCreateDTO dto) {
        log.info("开始创建权限: permissionName={}, permissionCode={}", dto.getPermissionName(), dto.getPermissionCode());
        
        // 参数校验
        if (dto == null) {
            throw new RuntimeException("权限信息不能为空");
        }
        
        // 检查权限编码是否已存在
        if (checkPermissionCodeExists(dto.getPermissionCode(), null, dto.getTenantId())) {
            throw new RuntimeException("权限编码已存在: " + dto.getPermissionCode());
        }
        
        // 检查权限名称是否已存在
        if (checkPermissionNameExists(dto.getPermissionName(), null, dto.getTenantId())) {
            throw new RuntimeException("权限名称已存在: " + dto.getPermissionName());
        }
        
        // 如果有父权限，检查父权限是否存在
        if (dto.getParentId() != null && dto.getParentId() > 0) {
            Permission parentPermission = permissionMapper.selectById(dto.getParentId());
            if (parentPermission == null || !parentPermission.getTenantId().equals(dto.getTenantId())) {
                throw new RuntimeException("父权限不存在");
            }
        }
        
        // 创建权限实体
        Permission permission = new Permission();
        BeanUtils.copyProperties(dto, permission);
        permission.setStatus(1); // 默认启用
        permission.setCreateTime(LocalDateTime.now());
        permission.setUpdateTime(LocalDateTime.now());
        
        // 保存权限
        int result = permissionMapper.insert(permission);
        if (result <= 0) {
            throw new RuntimeException("创建权限失败");
        }
        
        log.info("权限创建成功: permissionId={}, permissionName={}", permission.getId(), dto.getPermissionName());
        return permission.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"permissionPage", "permissionDetail"}, allEntries = true)
    public Boolean updatePermission(PermissionUpdateDTO dto) {
        log.info("开始更新权限: permissionId={}, permissionName={}", dto.getId(), dto.getPermissionName());
        
        // 参数校验
        if (dto == null || dto.getId() == null) {
            throw new RuntimeException("权限ID不能为空");
        }
        
        // 检查权限是否存在
        Permission existingPermission = permissionMapper.selectById(dto.getId());
        if (existingPermission == null || !existingPermission.getTenantId().equals(dto.getTenantId())) {
            throw new RuntimeException("权限不存在");
        }
        
        // 检查权限编码是否已存在（排除当前权限）
        if (checkPermissionCodeExists(dto.getPermissionCode(), dto.getId(), dto.getTenantId())) {
            throw new RuntimeException("权限编码已存在: " + dto.getPermissionCode());
        }
        
        // 检查权限名称是否已存在（排除当前权限）
        if (checkPermissionNameExists(dto.getPermissionName(), dto.getId(), dto.getTenantId())) {
            throw new RuntimeException("权限名称已存在: " + dto.getPermissionName());
        }
        
        // 如果有父权限，检查父权限是否存在且不能是自己
        if (dto.getParentId() != null && dto.getParentId() > 0) {
            if (dto.getParentId().equals(dto.getId())) {
                throw new RuntimeException("父权限不能是自己");
            }
            Permission parentPermission = permissionMapper.selectById(dto.getParentId());
            if (parentPermission == null || !parentPermission.getTenantId().equals(dto.getTenantId())) {
                throw new RuntimeException("父权限不存在");
            }
        }
        
        // 更新权限实体
        Permission permission = new Permission();
        BeanUtils.copyProperties(dto, permission);
        permission.setUpdateTime(LocalDateTime.now());
        
        // 更新权限
        int result = permissionMapper.updateById(permission);
        if (result <= 0) {
            throw new RuntimeException("更新权限失败");
        }
        
        log.info("权限更新成功: permissionId={}, permissionName={}", dto.getId(), dto.getPermissionName());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"permissionPage", "permissionDetail", "rolePermissionPage"}, allEntries = true)
    public Boolean deletePermission(Long id, Long tenantId) {
        log.info("开始删除权限: permissionId={}, tenantId={}", id, tenantId);
        
        // 参数校验
        if (id == null || tenantId == null) {
            throw new RuntimeException("权限ID和租户ID不能为空");
        }
        
        // 检查权限是否存在
        Permission permission = permissionMapper.selectById(id);
        if (permission == null || !permission.getTenantId().equals(tenantId)) {
            throw new RuntimeException("权限不存在");
        }
        
        // 检查是否有子权限
        if (hasChildren(id, tenantId)) {
            throw new RuntimeException("存在子权限，无法删除");
        }
        
        // 删除权限（逻辑删除）
        permission.setDeleted(1);
        permission.setUpdateTime(LocalDateTime.now());
        int result = permissionMapper.updateById(permission);
        
        if (result <= 0) {
            throw new RuntimeException("删除权限失败");
        }
        
        log.info("权限删除成功: permissionId={}", id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeletePermissions(List<Long> ids, Long tenantId) {
        log.info("开始批量删除权限: permissionIds={}, tenantId={}", ids, tenantId);
        
        // 参数校验
        if (CollectionUtils.isEmpty(ids) || tenantId == null) {
            throw new RuntimeException("权限ID列表和租户ID不能为空");
        }
        
        // 逐个删除权限
        for (Long id : ids) {
            deletePermission(id, tenantId);
        }
        
        log.info("批量删除权限成功: count={}", ids.size());
        return true;
    }

    @Override
    public PermissionVO getPermissionById(Long id, Long tenantId) {
        // 参数校验
        if (id == null || tenantId == null) {
            throw new RuntimeException("权限ID和租户ID不能为空");
        }
        
        // 查询权限
        Permission permission = permissionMapper.selectById(id);
        if (permission == null || !permission.getTenantId().equals(tenantId) || permission.getDeleted() == 1) {
            return null;
        }
        
        // 转换为VO
        return convertToPermissionVO(permission);
    }

    @Override
    @Cacheable(value = "permissionPage", 
               key = "T(com.cencat.user.config.CacheConfig.CacheKeyGenerator).generatePermissionPageKey(#queryDTO.tenantId, #queryDTO.pageNum, #queryDTO.pageSize, #queryDTO.permissionName, #queryDTO.status)",
               condition = "#queryDTO != null and #queryDTO.tenantId != null")
    public PageResponse<PermissionListVO> getPermissionPage(PermissionQueryDTO queryDTO) {
        // 参数校验
        if (queryDTO == null) {
            throw new RuntimeException("查询条件不能为空");
        }
        
        // 设置默认分页参数
        if (queryDTO.getPageNum() == null || queryDTO.getPageNum() <= 0) {
            queryDTO.setPageNum(1);
        }
        if (queryDTO.getPageSize() == null || queryDTO.getPageSize() <= 0) {
            queryDTO.setPageSize(10);
        }
        
        // 构建分页查询参数
        PaginationHelper.PageQuery pageQuery = new PaginationHelper.PageQuery();
        pageQuery.setCurrent(queryDTO.getPageNum().longValue());
        pageQuery.setSize(queryDTO.getPageSize().longValue());
        
        // 构建查询条件
        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id", queryDTO.getTenantId());
        queryWrapper.eq("is_deleted", 0);
        
        if (StringUtils.hasText(queryDTO.getPermissionName())) {
            queryWrapper.like("permission_name", queryDTO.getPermissionName());
        }
        
        if (StringUtils.hasText(queryDTO.getPermissionCode())) {
            queryWrapper.like("permission_code", queryDTO.getPermissionCode());
        }
        
        if (queryDTO.getPermissionType() != null) {
            queryWrapper.eq("permission_type", queryDTO.getPermissionType());
        }
        
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq("status", queryDTO.getStatus());
        }
        
        queryWrapper.orderByDesc("create_time");
        
        // 执行分页查询并转换为VO
        return PaginationHelper.executePage(permissionMapper, pageQuery, queryWrapper, this::convertToPermissionListVO);
    }

    @Override
    public List<PermissionListVO> getPermissionList(PermissionQueryDTO queryDTO) {
        // 参数校验
        if (queryDTO == null) {
            throw new RuntimeException("查询条件不能为空");
        }
        
        // 构建查询条件
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getTenantId, queryDTO.getTenantId())
                .eq(Permission::getDeleted, 0)
                .like(CencatStringUtils.isNotBlank(queryDTO.getPermissionName()), Permission::getPermissionName, queryDTO.getPermissionName())
                .like(CencatStringUtils.isNotBlank(queryDTO.getPermissionCode()), Permission::getPermissionCode, queryDTO.getPermissionCode())
                .eq(queryDTO.getPermissionType() != null, Permission::getPermissionType, queryDTO.getPermissionType())
                .eq(queryDTO.getParentId() != null, Permission::getParentId, queryDTO.getParentId())
                .eq(queryDTO.getStatus() != null, Permission::getStatus, queryDTO.getStatus())
                .orderByAsc(Permission::getSortOrder)
                .orderByAsc(Permission::getCreateTime);
        
        // 查询权限列表
        List<Permission> permissions = permissionMapper.selectList(wrapper);
        
        // 转换为VO
        return permissions.stream()
                .map(this::convertToPermissionListVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<PermissionVO> getPermissionTree(Long tenantId) {
        // 参数校验
        if (tenantId == null) {
            throw new RuntimeException("租户ID不能为空");
        }
        
        // 查询所有权限
        List<Permission> allPermissions = permissionMapper.selectPermissionTree(tenantId);
        
        // 转换为VO
        List<PermissionVO> permissionVOs = allPermissions.stream()
                .map(this::convertToPermissionVO)
                .collect(Collectors.toList());
        
        // 构建树形结构
        return buildPermissionTree(permissionVOs, 0L);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean enablePermission(Long id, Long tenantId) {
        return updatePermissionStatus(id, 1, tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean disablePermission(Long id, Long tenantId) {
        return updatePermissionStatus(id, 0, tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchUpdatePermissionStatus(List<Long> ids, Integer status, Long tenantId) {
        log.info("开始批量更新权限状态: permissionIds={}, status={}, tenantId={}", ids, status, tenantId);
        
        // 参数校验
        if (CollectionUtils.isEmpty(ids) || status == null || tenantId == null) {
            throw new RuntimeException("参数不能为空");
        }
        
        // 批量更新状态
        int result = permissionMapper.batchUpdateStatus(ids, status, null, tenantId);
        
        if (result <= 0) {
            throw new RuntimeException("批量更新权限状态失败");
        }
        
        log.info("批量更新权限状态成功: count={}", result);
        return true;
    }

    @Override
    public Boolean checkPermissionCodeExists(String permissionCode, Long excludeId, Long tenantId) {
        if (CencatStringUtils.isBlank(permissionCode) || tenantId == null) {
            return false;
        }
        
        Long excludeIdValue = excludeId != null ? excludeId : -1L;
        int count = permissionMapper.checkPermissionCodeExists(permissionCode, excludeIdValue, tenantId);
        return count > 0;
    }

    @Override
    public Boolean checkPermissionNameExists(String permissionName, Long excludeId, Long tenantId) {
        if (CencatStringUtils.isBlank(permissionName) || tenantId == null) {
            return false;
        }
        
        Long excludeIdValue = excludeId != null ? excludeId : -1L;
        int count = permissionMapper.checkPermissionNameExists(permissionName, excludeIdValue, tenantId);
        return count > 0;
    }

    @Override
    public List<PermissionVO> getChildrenByParentId(Long parentId, Long tenantId) {
        // 参数校验
        if (parentId == null || tenantId == null) {
            throw new RuntimeException("父权限ID和租户ID不能为空");
        }
        
        // 查询子权限
        List<Permission> children = permissionMapper.selectByParentId(parentId, tenantId);
        
        // 转换为VO
        return children.stream()
                .map(this::convertToPermissionVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<PermissionVO> getPermissionsByType(Integer permissionType, Long tenantId) {
        // 参数校验
        if (permissionType == null || tenantId == null) {
            throw new RuntimeException("权限类型和租户ID不能为空");
        }
        
        // 查询权限
        List<Permission> permissions = permissionMapper.selectByPermissionType(permissionType, tenantId);
        
        // 转换为VO
        return permissions.stream()
                .map(this::convertToPermissionVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<PermissionVO> getPermissionsByUserId(Long userId, Long tenantId) {
        // 参数校验
        if (userId == null || tenantId == null) {
            throw new RuntimeException("用户ID和租户ID不能为空");
        }
        
        // 查询用户权限
        List<Permission> permissions = permissionMapper.selectPermissionsByUserId(userId, tenantId);
        
        // 转换为VO
        return permissions.stream()
                .map(this::convertToPermissionVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<PermissionVO> getPermissionsByRoleId(Long roleId, Long tenantId) {
        // 参数校验
        if (roleId == null || tenantId == null) {
            throw new RuntimeException("角色ID和租户ID不能为空");
        }
        
        // 查询角色权限
        List<Permission> permissions = permissionMapper.selectPermissionsByRoleId(roleId, tenantId);
        
        // 转换为VO
        return permissions.stream()
                .map(this::convertToPermissionVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<PermissionVO> getPermissionsByIds(List<Long> permissionIds, Long tenantId) {
        // 参数校验
        if (CollectionUtils.isEmpty(permissionIds) || tenantId == null) {
            return new ArrayList<>();
        }
        
        // 查询权限
        String permissionIdsStr = permissionIds.stream().map(String::valueOf).collect(Collectors.joining(","));
        List<Permission> permissions = permissionMapper.selectByIds(permissionIdsStr, tenantId);
        
        // 转换为VO
        return permissions.stream()
                .map(this::convertToPermissionVO)
                .collect(Collectors.toList());
    }

    @Override
    public Boolean hasChildren(Long parentId, Long tenantId) {
        if (parentId == null || tenantId == null) {
            return false;
        }
        
        int count = permissionMapper.countChildrenByParentId(parentId, tenantId);
        return count > 0;
    }

    @Override
    public Long getPermissionCount(Long tenantId) {
        if (tenantId == null) {
            return 0L;
        }
        
        PermissionQueryDTO queryDTO = new PermissionQueryDTO();
        queryDTO.setTenantId(tenantId);
        return permissionMapper.countPermissions(queryDTO);
    }

    @Override
    public PermissionVO getPermissionByCode(String permissionCode, Long tenantId) {
        if (CencatStringUtils.isBlank(permissionCode) || tenantId == null) {
            return null;
        }
        
        Permission permission = permissionMapper.selectByPermissionCode(permissionCode, tenantId);
        return permission != null ? convertToPermissionVO(permission) : null;
    }

    @Override
    public PermissionVO getPermissionByName(String permissionName, Long tenantId) {
        if (CencatStringUtils.isBlank(permissionName) || tenantId == null) {
            return null;
        }
        
        Permission permission = permissionMapper.selectByPermissionName(permissionName, tenantId);
        return permission != null ? convertToPermissionVO(permission) : null;
    }

    /**
     * 更新权限状态
     * @param id 权限ID
     * @param status 状态
     * @param tenantId 租户ID
     * @return 是否成功
     */
    private Boolean updatePermissionStatus(Long id, Integer status, Long tenantId) {
        log.info("开始更新权限状态: permissionId={}, status={}, tenantId={}", id, status, tenantId);
        
        // 参数校验
        if (id == null || status == null || tenantId == null) {
            throw new RuntimeException("参数不能为空");
        }
        
        // 检查权限是否存在
        Permission permission = permissionMapper.selectById(id);
        if (permission == null || !permission.getTenantId().equals(tenantId)) {
            throw new RuntimeException("权限不存在");
        }
        
        // 更新状态
        permission.setStatus(status);
        permission.setUpdateTime(LocalDateTime.now());
        int result = permissionMapper.updateById(permission);
        
        if (result <= 0) {
            throw new RuntimeException("更新权限状态失败");
        }
        
        log.info("权限状态更新成功: permissionId={}, status={}", id, status);
        return true;
    }

    /**
     * 转换为权限VO
     * @param permission 权限实体
     * @return 权限VO
     */
    private PermissionVO convertToPermissionVO(Permission permission) {
        if (permission == null) {
            return null;
        }
        
        PermissionVO vo = new PermissionVO();
        BeanUtils.copyProperties(permission, vo);
        
        // 设置权限类型名称
        vo.setPermissionTypeName(getPermissionTypeName(permission.getPermissionType()));
        
        // 设置状态名称
        vo.setStatusName(permission.getStatus() == 1 ? "正常" : "禁用");
        
        // 检查是否有子权限
        vo.setHasChildren(hasChildren(permission.getId(), permission.getTenantId()));
        
        return vo;
    }

    /**
     * 转换为权限列表VO
     * @param permission 权限实体
     * @return 权限列表VO
     */
    private PermissionListVO convertToPermissionListVO(Permission permission) {
        if (permission == null) {
            return null;
        }
        
        PermissionListVO vo = new PermissionListVO();
        BeanUtils.copyProperties(permission, vo);
        
        // 设置权限类型名称
        vo.setPermissionTypeName(getPermissionTypeName(permission.getPermissionType()));
        
        // 设置状态名称
        vo.setStatusName(permission.getStatus() == 1 ? "正常" : "禁用");
        
        // 检查是否有子权限
        vo.setHasChildren(hasChildren(permission.getId(), permission.getTenantId()));
        
        // 统计子权限数量
        vo.setChildrenCount(permissionMapper.countChildrenByParentId(permission.getId(), permission.getTenantId()));
        
        return vo;
    }

    /**
     * 构建权限树形结构
     * @param permissions 权限列表
     * @param parentId 父权限ID
     * @return 权限树形列表
     */
    private List<PermissionVO> buildPermissionTree(List<PermissionVO> permissions, Long parentId) {
        List<PermissionVO> tree = new ArrayList<>();
        
        for (PermissionVO permission : permissions) {
            if (parentId.equals(permission.getParentId())) {
                List<PermissionVO> children = buildPermissionTree(permissions, permission.getId());
                permission.setChildren(children);
                permission.setHasChildren(!CollectionUtils.isEmpty(children));
                tree.add(permission);
            }
        }
        
        return tree;
    }

    /**
     * 获取权限类型名称
     * @param permissionType 权限类型
     * @return 权限类型名称
     */
    private String getPermissionTypeName(Integer permissionType) {
        if (permissionType == null) {
            return "未知";
        }
        
        switch (permissionType) {
            case 1:
                return "菜单";
            case 2:
                return "按钮";
            case 3:
                return "接口";
            default:
                return "未知";
        }
    }
}